import { dom, Nodes } from '@knno/dom';
import '../../dict';
import { actionQueue } from '../../tools/actionQueue';
import { button } from '../button/button';
import { DialogBase } from '../dialog/dialogBase';
import { actionStyle } from './action.css';
import { DATA } from '../symbol';
import { DICT } from '../../dict';

interface Callback {
	(): void;
}

interface ActionBox {
	[DATA]: { onOk?: Callback; title?: string; visible: boolean; noBar?: boolean };
}

class ActionBox extends DialogBase {
	protected get box(): Nodes {
		return this.query(':scope>div.panel>div.content');
	}
	protected getPanel(): Nodes {
		return this.query(':scope>div.panel');
	}
	constructor() {
		const box = dom
			.div(actionStyle)
			.append(dom.div('panel').attr('tabindex', '0').append(dom.div('button-bar'), dom.div('content')));
		super(box);
	}

	private renderBar() {
		const bar = this.query(':scope>div.panel>div.button-bar').html('');
		if (typeof this[DATA].onOk === 'function' && !this[DATA].noBar) {
			bar.addClass('has-button').append(
				button('button')
					.text(DICT.cancel)
					.type('info-text')
					.on('click', () => {
						this.emit(new Event('close'));
					}),
				dom.h4().text(this[DATA].title ?? ''),
				button('button')
					.text(DICT.ok)
					.type('primary-text')
					.on('click', () => {
						this[DATA].onOk?.();
					})
			);
		} else {
			bar.removeClass('has-button').append(dom.h4().text(this[DATA].title ?? ''));
		}
		if (this[DATA].title && !this[DATA].noBar) {
			bar.addClass('has-title');
		} else {
			bar.removeClass('has-title');
		}
	}

	onOK(callback: (() => void) | null): this {
		if (callback) {
			this[DATA].onOk = callback;
		} else {
			delete this[DATA].onOk;
		}
		this.renderBar();
		return this;
	}

	title(text: string | null): this {
		if (text) {
			this[DATA].title = text;
		} else {
			delete this[DATA].title;
		}
		this.renderBar();
		return this;
	}

	noBar(value: boolean): this {
		this[DATA].noBar = value;
		this.renderBar();
		return this;
	}
}

interface ActionEntry {
	action: ActionBox;
	show(): void;
	hide(): void;
}

const queue = actionQueue<ActionEntry>(200);

let currentAction: ActionEntry | null = null;

interface ActionOption {
	align?: 'bottom' | 'top' | 'left' | 'right';
	autoClose?: boolean;
}

export const Action = {
	get current() {
		return currentAction;
	},
	show(elem: Nodes, options?: ActionOption) {
		const autoClose = options?.autoClose ?? true;
		const actionEntry = {
			action: new ActionBox()
				.addClass(options?.align ?? 'bottom')
				.append(...elem)
				.autoClose(true)
				.on('close', () => {
					if (autoClose) queue.close();
				}),
			show() {
				this.action.show();
				currentAction = actionEntry;
			},
			hide() {
				currentAction = null;
				this.action.close();
			},
		};
		if (autoClose) {
			queue.show(actionEntry);
		} else {
			actionEntry.action.show();
		}
		return actionEntry.action;
	},
	close() {
		queue.close();
	},
};

DialogBase.actionHandler = Action;
